package com.ete.service.service.hardware

import com.blankj.utilcode.util.*
import com.ete.service.db.EteDatabase
import com.ete.service.dialog.CommonDialog
import com.ete.service.entry.dialog.CommonDialogEntry
import com.ete.service.entry.hardware.*
import com.ete.service.manager.ManagerConstant
import com.ete.service.manager.hardware.HardwareManager
import com.ete.service.net.api.ServiceApi
import com.ete.service.net.bean.BaseResponse
import com.ete.service.net.exception.ExceptionTranslate
import com.ete.service.net.http.RetrofitClient
import com.ete.service.service.R
import com.ete.service.util.ServiceUtil
import com.ete.service.util.log.EteLog
import com.ete.service.util.unique.UniqueUtils
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.lang.reflect.Method
import java.util.*
import java.util.concurrent.TimeUnit

/**
 * Author:LiXian
 * <p>
 * Desc:上报硬件信息
 * Version:1.0
 * date 2024/1/12 13:07
 */
object UploadHardwareUtil {

    private lateinit var mHardwareEntry: HardwareEntry

    private const val BANNED_DEVICE = "BANNED_DEVICE"

    /**
     * 是否禁用设备
     */
    private var isBannedDevice: Boolean? = null

    /**
     * 时间格式（yyyy-MM-dd HH:mm:ss）
     */
    private val dateFormat = TimeUtils.getSafeDateFormat(ManagerConstant.TIME_FORMAT_FULL)

    /**
     * 本次启动是否已插入数据, 1次启动只插入1条数据
     */
    private var isInserted = false

    /**
     * 是否已开启上报
     */
    private var isStartUpload = false

    private var isShowDialog = false

    /**
     * 此条数据唯一标示
     */
    private var deviceRecordId: String? = null

    /**
     * 定时任务
     */
    private var mUploadTask: ThreadUtils.SimpleTask<String>? = null

    /**
     * 是否正在添加硬件信息
     */
    private var isAddHardware: Boolean = false

    /**
     * 上次关机时间
     */
    private var offTime: String = ""

    /**
     * 本次开机时间
     */
    private var onTime: String = ""

    /**
     * 主机ID
     */
    private var mHostId: String = ""

    /**
     * 初始化
     */
    @JvmStatic
    fun init(hardwareEntry: HardwareEntry) {
        ServiceUtil.executeByIo(doInBackground = {
            mHardwareEntry = hardwareEntry
            mHostId = mHardwareEntry.deviceId
            EteDatabase.init(Utils.getApp(), hardwareEntry.mDBPath)
            initOffAndOnTime()
        })
    }

    /**
     * 添加单机设备
     */
    @JvmStatic
    fun addSalveDevice(mEntry: SlaveEntry) {
        isAddHardware = true
        ServiceUtil.executeByIo(doInBackground = {
            val entry = convertHardwareInfo(mEntry)
            EteDatabase.getInstance().getHardwareInfoDao().insertItem(entry)
        }, onDone = {
            isAddHardware = false
        })
    }

    /**
     * 添加单机设备列表
     */
    @JvmStatic
    fun addSalveDeviceList(mEntries: List<SlaveEntry>) {
        isAddHardware = true
        ServiceUtil.executeByIo(doInBackground = {
            val entries: List<HardwareInfoEntry> = mEntries.map { convertHardwareInfo(it) }
            EteDatabase.getInstance().getHardwareInfoDao().insertItems(entries)
        }, onDone = {
            isAddHardware = false
        })
    }

    /**
     * 上报硬件信息
     */
    @JvmStatic
    fun startUploadHardwareInfo() {
        if (isStartUpload) return
        isStartUpload = true
        isShowDialog = false
        initUploadTask()
    }

    /**
     * 停止上报硬件信息
     */
    @JvmStatic
    fun stopUploadHardwareInfo() {
        isStartUpload = false
        mUploadTask?.cancel()
        mUploadTask = null
    }

    /**
     * 初始化开关机时间
     *
     * 上次有主机信息记录，则去上次的最后开机时间作为本次记录的关机时间，没有记录则去当前时间作为关机时间
     */
    private fun initOffAndOnTime() {
        val deviceInfo = EteDatabase.getInstance().getHardwareInfoDao().getLatestUploadHostHardwareInfo()
        onTime = dateFormat.format(Date())
        offTime = deviceInfo?.onTime ?: onTime
    }

    /**
     * 检查禁用设备
     */
    @JvmStatic
    private fun checkBannedDevice() {
        isBannedDevice = isBannedDevice ?: SPUtils.getInstance().getBoolean(BANNED_DEVICE, false)
        EteLog.d(HardwareManager.TAG, "检查禁用设备isBannedDevice:[$isBannedDevice]")
        if (isBannedDevice!!) {
            showDeviceBannedDialog()
        }
    }

    /**
     * 初始化上报任务
     */
    private fun initUploadTask() {
        mUploadTask = object : ThreadUtils.SimpleTask<String>() {
            override fun doInBackground(): String {
                // 本次还没插入数据的情况，先插入数据
                if (!isInserted) {
                    deviceRecordId = UniqueUtils.getUniqueFlag()
                    val hostHardwareInfo = HardwareInfoEntry(
                            serialNumber = deviceRecordId!!,
                            name = DeviceUtils.getModel().uppercase(),
                            type = ManagerConstant.UPLOAD_TYPE_HOST,
                            deviceId = mHostId,
                            networkType = getNetworkType(),
                            osVersion = DeviceUtils.getSDKVersionName(),
                            appVersion = AppUtils.getAppVersionName(),
                            offTime = offTime,
                            onTime = onTime,
                            firmwareVersion = getFirmwareVersion(),
                            hardwareVersion = getHardwareVersion(),
                            connectType = ManagerConstant.CONNECT_TYPE_OTHER,
                            uploadState = ManagerConstant.HARDWARE_UNLOADED,
                            createTime = System.currentTimeMillis()
                    )
                    EteDatabase.getInstance().getHardwareInfoDao().saveOrUpdate(hostHardwareInfo)
                    isInserted = true
                }

                // 有网络的情况下,  上传所有未上传的设备信息
                if (NetworkUtils.isAvailable() && NetworkUtils.getNetworkType() != NetworkUtils.NetworkType.NETWORK_NO) {
                    // 有网络，先更新最新的主机设备记录的网络类型
                    deviceRecordId?.let {
                        EteDatabase.getInstance().getHardwareInfoDao().updateDeviceNetworkType(it, getNetworkType())
                    }
                    // 上传设备信息数据, 把未上传的数据再次上传
                    val notUploadDeviceList = EteDatabase.getInstance().getHardwareInfoDao().getNotUploadHardwareInfoList()
                    if (notUploadDeviceList.isNotEmpty()) {
                        EteLog.i(HardwareManager.TAG, "Start upload device info. deviceList:[$notUploadDeviceList]")
                        uploadDeviceInfo(notUploadDeviceList)
                    }
                } else {
                    checkBannedDevice()
                }

                // 刷新本次设备记录的最后关机时间
                val deviceInfo = EteDatabase.getInstance().getHardwareInfoDao().getLatestUploadHostHardwareInfo()
                deviceInfo?.let {
                    it.onTime = dateFormat.format(System.currentTimeMillis())
                    EteDatabase.getInstance().getHardwareInfoDao().saveOrUpdate(it)
                }
                return ""
            }

            override fun onSuccess(result: String) {

            }

            override fun onFail(t: Throwable?) {
                super.onFail(t)
                stopUploadHardwareInfo()
                startUploadHardwareInfo()
            }
        }
        ThreadUtils.executeBySingleAtFixRate(mUploadTask, 2L, 60L, TimeUnit.SECONDS)
    }

    /**
     * 上报硬件信息
     *
     * @param mHardwareEntries 硬件信息
     */
    @JvmStatic
    private fun uploadDeviceInfo(mHardwareEntries: List<HardwareInfoEntry>) {
        if (isAddHardware) return
        val mResponseCallback = object : Callback<BaseResponse<StateEntry>> {
            override fun onResponse(call: Call<BaseResponse<StateEntry>>,
                                    response: Response<BaseResponse<StateEntry>>) {
                if (!response.isSuccessful) {
                    EteLog.d(HardwareManager.TAG, "上报硬件信息，请求服务器错误: ${response.message()}")
                    return
                }
                val result = response.body()
                if (result == null) {
                    EteLog.d(HardwareManager.TAG, "上报硬件信息，服务器响应为空")
                    return
                }
                val isSuccess = result.succ
                if (isSuccess == null || !isSuccess) {
                    EteLog.d(HardwareManager.TAG, ("上报硬件信息，" + (result.msg
                            ?: "请求服务器错误")))
                    return
                }
                val mData = result.data
                if (mData == null) {
                    EteLog.d(HardwareManager.TAG, "上报硬件信息失败")
                    return
                }
                EteLog.d(HardwareManager.TAG, "上报硬件信息成功")
                paraResultData(mData)
                deleteWithoutId(mHardwareEntries)
            }

            override fun onFailure(call: Call<BaseResponse<StateEntry>>, t: Throwable) {
                t.printStackTrace()
                val message = ExceptionTranslate.translateException(t).message
                EteLog.d(HardwareManager.TAG, "上报硬件信息错误message:[$message]")
            }
        }
        val mConfig = HardwareConfig(mHostId, mHardwareEntries)
        RetrofitClient.createService(ServiceApi::class.java)
            .uploadHardwareInfo(mConfig).enqueue(mResponseCallback)
    }

    /**
     * 删除已上传的硬件信息
     */
    private fun deleteWithoutId(mHardwareEntries: List<HardwareInfoEntry>) {
        mHardwareEntries.forEach { it.uploadState = 1 }
        EteDatabase.getInstance().getHardwareInfoDao().saveAll(mHardwareEntries)
        // 本次启动主机设备记录不为空时, 删除该条记录外的所有设备记录
        // 本次启动主机设备记录信息需要被下次启动记录使用，因此不能删除
        if (deviceRecordId != null) {
            EteDatabase.getInstance().getHardwareInfoDao().deleteWithoutId(deviceRecordId)
        }
    }

    /**
     * 解析数据
     *
     * 1、存在禁用的设备，弹窗提醒
     */
    @JvmStatic
    private fun paraResultData(mEntry: StateEntry) {
        isBannedDevice = ManagerConstant.HARDWARE_DEVICE_STATE_BANNED == mEntry.state
        EteLog.d(HardwareManager.TAG, "设备:[${mHostId}]，名称:[${DeviceUtils.getModel()}]，是否禁用isBannedDevice:[$isBannedDevice]")
        SPUtils.getInstance().put(BANNED_DEVICE, isBannedDevice!!)
        if (isBannedDevice!!) {
            showDeviceBannedDialog()
        } else {
            EteLog.d(HardwareManager.TAG, "设备:[${mHostId}]，名称:[${DeviceUtils.getModel()}]，未禁用")
        }
    }

    /**
     * 设备禁用提醒
     *
     * 1、点击确定，直接结束APP
     */
    @JvmStatic
    private fun showDeviceBannedDialog() {
        if (isShowDialog) {
            EteLog.d(HardwareManager.TAG, "已显示禁用对话框")
            return
        }
        val mContext = ActivityUtils.getTopActivity() ?: return
        isShowDialog = true
        ThreadUtils.runOnUiThread {
            val mDialogEntry = CommonDialogEntry(mContext = mContext,
                    mTitle = mContext.getString(R.string.hardware_exception_title),
                    mContent = mContext.getString(R.string.hardware_exception_content),
                    themeColor = mHardwareEntry.mThemeColor,
                    isShowLoading = false,
                    isShowSure = true,
                    isShowCancel = false,
                    isShowClose = false,
                    isOutTouchCancel = false,
                    mSureCallback = {
                        AppUtils.exitApp()
                        true
                    }
            )
            val mDialog = CommonDialog(mDialogEntry)
            mDialog.initDialog()
            mDialog.show()
        }
    }

    /**
     * 获取网络类型
     */
    @JvmStatic
    private fun getNetworkType(): Int {
        // 0:没有网络 1:蜂窝网络 2: WIFI网络
        return when (NetworkUtils.getNetworkType()) {
            NetworkUtils.NetworkType.NETWORK_WIFI -> 2
            NetworkUtils.NetworkType.NETWORK_2G,
            NetworkUtils.NetworkType.NETWORK_3G,
            NetworkUtils.NetworkType.NETWORK_4G,
            NetworkUtils.NetworkType.NETWORK_5G -> 1

            else -> 0
        }
    }

    /**
     * 获取系统固件版本号
     */
    @JvmStatic
    fun getFirmwareVersion(): String {
        return try {
            val cls = Class.forName("android.os.SystemProperties")
            val method: Method = cls.getMethod("get", String::class.java)
            method.isAccessible = true
            val value = method.invoke(cls, "ro.vendor.sdkversion")
            value?.toString() ?: ""
        } catch (e: java.lang.Exception) {
            ""
        }
    }

    /**
     * 获取硬件版本号
     */
    @JvmStatic
    private fun getHardwareVersion(): String {
        return ""
    }

    @JvmStatic
    private fun convertHardwareInfo(mEntry: SlaveEntry): HardwareInfoEntry {
        val connectType = when (mEntry.connectType) {
            ConnectType.CONNECT_24G -> ManagerConstant.CONNECT_TYPE_24G
            ConnectType.CONNECT_BLE -> ManagerConstant.CONNECT_TYPE_BLE
            ConnectType.CONNECT_TUYA -> ManagerConstant.CONNECT_TYPE_TUYA
            ConnectType.CONNECT_58G -> ManagerConstant.CONNECT_TYPE_58G
            ConnectType.CONNECT_OTHER -> ManagerConstant.CONNECT_TYPE_OTHER
        }
        return HardwareInfoEntry(
                serialNumber = UniqueUtils.getUniqueFlag(),
                name = mEntry.slaveName,
                type = ManagerConstant.UPLOAD_TYPE_SUB,
                deviceId = mEntry.slaveId,
                networkType = getNetworkType(),
                osVersion = DeviceUtils.getSDKVersionName(),
                appVersion = AppUtils.getAppVersionName(),
                offTime = offTime,
                onTime = onTime,
                firmwareVersion = mEntry.firmwareVersion,
                hardwareVersion = mEntry.firmwareVersion,
                connectType = connectType,
                uploadState = ManagerConstant.HARDWARE_UNLOADED,
                createTime = System.currentTimeMillis()
        )
    }
}